home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / sendmail / sendmail-5.65c+IDA-1.4.4.1 / src / util.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-08-08  |  16.4 KB  |  973 lines

  1. /*
  2.  * Copyright (c) 1983 Eric P. Allman
  3.  * Copyright (c) 1988 Regents of the University of California.
  4.  * All rights reserved.
  5.  *
  6.  * Redistribution and use in source and binary forms are permitted provided
  7.  * that: (1) source distributions retain this entire copyright notice and
  8.  * comment, and (2) distributions including binaries display the following
  9.  * acknowledgement:  ``This product includes software developed by the
  10.  * University of California, Berkeley and its contributors'' in the
  11.  * documentation or other materials provided with the distribution and in
  12.  * all advertising materials mentioning features or use of this software.
  13.  * Neither the name of the University nor the names of its contributors may
  14.  * be used to endorse or promote products derived from this software without
  15.  * specific prior written permission.
  16.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  17.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  18.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  19.  */
  20.  
  21. #ifndef lint
  22. static char sccsid[] = "@(#)util.c    5.18 (Berkeley) 6/1/90";
  23. static char  rcsid[] = "@(#)$Id: util.c,v 5.18.0.14 1991/08/08 22:08:18 paul Exp $";
  24. #endif /* not lint */
  25.  
  26. #include "sendmail.h"
  27. #include <stdio.h>
  28. #include <sys/stat.h>
  29. #include <sysexits.h>
  30. #include <errno.h>
  31.  
  32. static void readtimeout();
  33.  
  34. static bool catPrint = FALSE;    /* xputs: print strings for catenation */
  35.  
  36. /*
  37. **  STRIPQUOTES -- Strip quotes & quote bits from a string.
  38. **
  39. **    Runs through a string and strips off unquoted quote
  40. **    characters and quote bits.  This is done in place.
  41. **
  42. **    Parameters:
  43. **        s -- the string to strip.
  44. **        qf -- if set, remove actual `` " '' characters
  45. **            as well as the quote bits.
  46. **
  47. **    Returns:
  48. **        none.
  49. **
  50. **    Side Effects:
  51. **        none.
  52. **
  53. **    Called By:
  54. **        deliver
  55. */
  56.  
  57. void
  58. stripquotes(s, qf)
  59.     char *s;
  60.     bool qf;
  61. {
  62.     register char *p;
  63.     register char *q;
  64.     register char c;
  65.  
  66.     if (s == NULL)
  67.         return;
  68.  
  69.     for (p = q = s; (c = *p++) != '\0'; )
  70.     {
  71.         if (c != '"' || !qf)
  72.             *q++ = c & 0177;
  73.     }
  74.     *q = '\0';
  75. }
  76. /*
  77. **  QSTRLEN -- give me the string length assuming 0200 bits add a char
  78. **
  79. **    Parameters:
  80. **        s -- the string to measure.
  81. **
  82. **    Returns:
  83. **        The length of s, including space for backslash escapes.
  84. **
  85. **    Side Effects:
  86. **        none.
  87. */
  88.  
  89. int
  90. qstrlen(s)
  91.     register const char *s;
  92. {
  93.     register int l = 0;
  94.     register char c;
  95.  
  96.     while ((c = *s++) != '\0')
  97.     {
  98.         if (bitset(0200, c))
  99.             l++;
  100.         l++;
  101.     }
  102.     return (l);
  103. }
  104. /*
  105. **  CAPITALIZE -- return a copy of a string, properly capitalized.
  106. **
  107. **    Parameters:
  108. **        s -- the string to capitalize.
  109. **
  110. **    Returns:
  111. **        a pointer to a properly capitalized string.
  112. **
  113. **    Side Effects:
  114. **        none.
  115. */
  116.  
  117. char *
  118. capitalize(s)
  119.     register const char *s;
  120. {
  121.     static char buf[50];
  122.     register char *p;
  123.  
  124.     if (strlen(s) >= 50)
  125.     {
  126.         errno = EFAULT; /* foregone conclusion */
  127.         syserr("buffer size exceeded in capitalize(), size needed %d",
  128.             strlen(s));
  129.         return(NULL);
  130.     }
  131.  
  132.     p = buf;
  133.  
  134.     for (;;)
  135.     {
  136.         while (!isalpha(*s) && *s != '\0')
  137.             *p++ = *s++;
  138.         if (*s == '\0')
  139.             break;
  140.         *p++ = toupper(*s);
  141.         s++;
  142.         while (isalpha(*s))
  143.             *p++ = *s++;
  144.     }
  145.  
  146.     *p = '\0';
  147.     return (buf);
  148. }
  149. /*
  150. **  XALLOC -- Allocate memory and bitch wildly on failure.
  151. **
  152. **    THIS IS A CLUDGE.  This should be made to give a proper
  153. **    error -- but after all, what can we do?
  154. **
  155. **    Parameters:
  156. **        sz -- size of area to allocate.
  157. **
  158. **    Returns:
  159. **        pointer to zeroed data region.
  160. **
  161. **    Side Effects:
  162. **        Memory is allocated.
  163. */
  164.  
  165. #ifdef __STDC__
  166. void *
  167. #else /* !__STDC__ */
  168. char *
  169. #endif /* __STDC__ */
  170. xalloc(sz)
  171.     register int sz;
  172. {
  173. #ifdef __STDC__
  174.     register void *p;
  175. #else /* !__STDC__ */
  176.     register char *p;
  177. #endif /* __STDC__ */
  178.  
  179.     p = malloc((unsigned) sz);
  180.     if (p == NULL)
  181.     {
  182.         syserr("Out of memory!!");
  183.         abort();
  184.         /* exit(EX_UNAVAILABLE); */
  185.     }
  186.     bzero((char *) p, sz);
  187.     return (p);
  188. }
  189. /*
  190. **  COPYPLIST -- copy list of pointers.
  191. **
  192. **    This routine is the equivalent of newstr for lists of
  193. **    pointers.
  194. **
  195. **    Parameters:
  196. **        list -- list of pointers to copy.
  197. **            Must be NULL terminated.
  198. **        copycont -- if TRUE, copy the contents of the vector
  199. **            (which must be a string) also.
  200. **
  201. **    Returns:
  202. **        a copy of 'list'.
  203. **
  204. **    Side Effects:
  205. **        none.
  206. */
  207.  
  208. char **
  209. copyplist(list, copycont)
  210.     char **list;
  211.     bool copycont;
  212. {
  213.     register char **vp;
  214.     register char **newvp;
  215.  
  216.     for (vp = list; *vp != NULL; vp++)
  217.         continue;
  218.  
  219.     vp++;
  220.  
  221.     newvp = (char **) xalloc((int) (vp - list) * sizeof *vp);
  222.     bcopy((char *) list, (char *) newvp, (int) (vp - list) * sizeof *vp);
  223.  
  224.     if (copycont)
  225.     {
  226.         for (vp = newvp; *vp != NULL; vp++)
  227.             *vp = newstr(*vp);
  228.     }
  229.  
  230.     return (newvp);
  231. }
  232. /*
  233. **  PRINTAV -- print argument vector.
  234. **
  235. **    Parameters:
  236. **        av -- argument vector.
  237. **
  238. **    Returns:
  239. **        none.
  240. **
  241. **    Side Effects:
  242. **        prints av.
  243. */
  244.  
  245. void
  246. printav(av)
  247.     register char **av;
  248. {
  249.     while (*av != NULL)
  250.     {
  251.         if (tTd(0, 44))
  252.             printf("\n\t%08x=", *av);
  253.         else
  254.             (void) putchar(' ');
  255.         xputs(*av++);
  256.     }
  257.     (void) putchar('\n');
  258. }
  259. /*
  260. **  LOWER -- turn letter into lower case.
  261. **
  262. **    Parameters:
  263. **        c -- character to turn into lower case.
  264. **
  265. **    Returns:
  266. **        c, in lower case.
  267. **
  268. **    Side Effects:
  269. **        none.
  270. */
  271.  
  272. char
  273. lower(c)
  274.     register char c;
  275. {
  276.     return (isascii(c) && isupper(c) ? tolower(c) : c);
  277. }
  278. /*
  279. **  XPUTS -- put string doing control escapes.
  280. **
  281. **    Parameters:
  282. **        s -- string to put.
  283. **
  284. **    Returns:
  285. **        none.
  286. **
  287. **    Side Effects:
  288. **        output to stdout
  289. */
  290.  
  291. void
  292. xputs(s)
  293.     register const char *s;
  294. {
  295.     register char c;
  296.     register struct metamac *m;
  297.  
  298.     if (s == MACNULL)
  299.     {
  300.         printf("<macnull>");
  301.         return;
  302.     }
  303.     if (s == NULL)
  304.     {
  305.         printf("<null>");
  306.         return;
  307.     }
  308.  
  309.     if (s[0] == MATCHREPL && isdigit(s[1]) && s[2] == '\0')
  310.     {
  311.         printf("$%c", s[1]);
  312.         return;
  313.     }
  314.     else
  315.         for (m = MetaMacros; m->metaname != '\0'; m++)
  316.             if (m->metaval == *s)
  317.             {
  318.                 printf("$%c%s", m->metaname, &s[1]);
  319.                 return;
  320.             }
  321.  
  322.     if (!catPrint)
  323.         (void) putchar('"');
  324.     while ((c = *s++) != '\0')
  325.     {
  326.         if (!isascii(c))
  327.         {
  328.             (void) putchar('\\');
  329.             c &= 0177;
  330.         }
  331.         if (c < 040 || c >= 0177)
  332.         {
  333.             (void) putchar('^');
  334.             c ^= 0100;
  335.         }
  336.         (void) putchar(c);
  337.     }
  338.     if (!catPrint)
  339.         (void) putchar('"');
  340.     (void) fflush(stdout);
  341. }
  342. /*
  343. **  MAKELOWER -- Translate a line into lower case
  344. **
  345. **    Parameters:
  346. **        p -- the string to translate.  If NULL, return is
  347. **            immediate.
  348. **
  349. **    Returns:
  350. **        none.
  351. **
  352. **    Side Effects:
  353. **        String pointed to by p is translated to lower case.
  354. **
  355. **    Called By:
  356. **        parse
  357. */
  358.  
  359. void
  360. makelower(p)
  361.     register char *p;
  362. {
  363.     register char c;
  364.     register bool quoted_string = FALSE;
  365.  
  366.     if (p == NULL)
  367.         return;
  368.     for (; (c = *p) != '\0'; p++)
  369.         if (c == '"')
  370.             quoted_string = !quoted_string;
  371.         else if (!quoted_string && isascii(c) && isupper(c))
  372.             *p = tolower(c);
  373. }
  374. /*
  375. **  BUILDFNAME -- build full name from gecos style entry.
  376. **
  377. **    This routine interprets the strange entry that would appear
  378. **    in the GECOS field of the password file.
  379. **
  380. **    Parameters:
  381. **        p -- name to build.
  382. **        login -- the login name of this user (for &).
  383. **        buf -- place to put the result.
  384. **
  385. **    Returns:
  386. **        none.
  387. **
  388. **    Side Effects:
  389. **        none.
  390. */
  391.  
  392. void
  393. buildfname(p, login, buf)
  394.     register const char *p;
  395.     const char *login;
  396.     char *buf;
  397. {
  398.     register char *bp = buf;
  399.  
  400.     if (*p == '*')
  401.         p++;
  402.     while (*p != '\0' && *p != ',' && *p != ';' && *p != '%')
  403.     {
  404.         if (*p == '&')
  405.         {
  406.             (void) strcpy(bp, login);
  407.             *bp = toupper(*bp);
  408.             while (*bp != '\0')
  409.                 bp++;
  410.             p++;
  411.         }
  412.         else
  413.             *bp++ = *p++;
  414.     }
  415.     *bp = '\0';
  416. }
  417. /*
  418. **  SAFEFILE -- return true if a file exists and is safe for a user.
  419. **
  420. **    Parameters:
  421. **        fn -- filename to check.
  422. **        uid -- uid to compare against.
  423. **        mode -- mode bits that must match.
  424. **
  425. **    Returns:
  426. **        TRUE if fn exists, is owned by uid, and matches mode.
  427. **        FALSE otherwise.
  428. **
  429. **    Side Effects:
  430. **        none.
  431. */
  432.  
  433. bool
  434. safefile(fn, uid, mode)
  435.     char *fn;
  436.     int uid;
  437.     int mode;
  438. {
  439.     struct stat stbuf;
  440.  
  441.     if (stat(fn, &stbuf) >= 0 && stbuf.st_uid == (uid_t) uid &&
  442.         (stbuf.st_mode & mode) == mode)
  443.         return (TRUE);
  444.     errno = 0;
  445.     return (FALSE);
  446. }
  447. /*
  448. **  FIXCRLF -- fix <CR><LF> in line.
  449. **
  450. **    Looks for the <CR><LF> combination and turns it into the
  451. **    UNIX canonical <NL> character.  It only takes one line,
  452. **    i.e., it is assumed that the first <NL> found is the end
  453. **    of the line.
  454. **
  455. **    Parameters:
  456. **        line -- the line to fix.
  457. **        stripnl -- if true, strip the newline also.
  458. **
  459. **    Returns:
  460. **        none.
  461. **
  462. **    Side Effects:
  463. **        line is changed in place.
  464. */
  465.  
  466. void
  467. fixcrlf(line, stripnl)
  468.     char *line;
  469.     bool stripnl;
  470. {
  471.     register char *p;
  472.  
  473.     p = index(line, '\n');
  474.     if (p == NULL)
  475.         return;
  476.     if (p > line && p[-1] == '\r')
  477.         p--;
  478.     if (!stripnl)
  479.         *p++ = '\n';
  480.     *p = '\0';
  481. }
  482. /*
  483. **  DFOPEN -- determined file open
  484. **
  485. **    This routine has the semantics of fopen, except that it will
  486. **    keep trying a few times to make this happen.  The idea is that
  487. **    on very loaded systems, we may run out of resources (inodes,
  488. **    whatever), so this tries to get around it.
  489. */
  490.  
  491. FILE *
  492. dfopen(filename, mode)
  493.     const char *filename;
  494.     const char *mode;
  495. {
  496.     register int tries;
  497.     register FILE *fp;
  498.  
  499.     for (tries = 0; tries < 10; tries++)
  500.     {
  501.         Xsleep((unsigned) (10 * tries));
  502.         errno = 0;
  503.         fp = fopen(filename, mode);
  504.         if (fp != NULL)
  505.             break;
  506.         if (errno != ENFILE && errno != EINTR)
  507.             break;
  508.     }
  509.     errno = 0;
  510.     return (fp);
  511. }
  512. /*
  513. **  PUTLINE -- put a line like fputs obeying SMTP conventions
  514. **
  515. **    This routine always guarantees outputing a newline (or CRLF,
  516. **    as appropriate) at the end of the string.
  517. **
  518. **    Parameters:
  519. **        l -- line to put.
  520. **        fp -- file to put it onto.
  521. **        m -- the mailer used to control output.
  522. **
  523. **    Returns:
  524. **        none
  525. **
  526. **    Side Effects:
  527. **        output of l to fp.
  528. */
  529.  
  530. #define SMTPLINELIM    990    /* maximum line length */
  531.  
  532. void
  533. putline(l, fp, m)
  534.     register char *l;
  535.     FILE *fp;
  536.     MAILER *m;
  537. {
  538.     register char *p;
  539.     int    limitsflag,    xdotflag;
  540.  
  541.     limitsflag = bitnset(M_LIMITS, m->m_flags);
  542.     /* strip out 0200 bits -- these can look like TELNET protocol */
  543.     /* damned well had better not have this bit set in constant strings! */
  544.     if (limitsflag)
  545.         for (p=l; (*p & ~0200)!=0; p++)
  546.             if (*p & 0200)
  547.                 *p &= ~0200;
  548.  
  549.     xdotflag = bitnset(M_XDOT, m->m_flags);
  550.     do
  551.     {
  552.         /* find the end of the line */
  553.         p = index(l, '\n');
  554.         if (p == NULL)
  555.             p = &l[strlen(l)];
  556.  
  557.         /* check for line overflow */
  558.         while (((p - l) > SMTPLINELIM) && limitsflag)
  559.         {
  560.             register char *q = &l[SMTPLINELIM - 1];
  561.  
  562.             if ((*l == '.') && xdotflag)
  563.                 (void) putc('.', fp);
  564.             fprintf(fp, "%.*s!%s", SMTPLINELIM-1, l, m->m_eol);
  565.             l = q;
  566.         }
  567.  
  568.         /* output last part */
  569.         if ((*l == '.') && xdotflag)
  570.             (void) putc('.', fp);
  571.  
  572.         /*
  573.          * Some broken compilers evaluate %.0s%s as %s%s.  This
  574.          * doubles blank lines.  I have to remember that portability
  575.          * is one of my goals (*sigh*).  -pbp
  576.          */
  577.         if (p == l)
  578.             fprintf(fp, "%s", m->m_eol);
  579.         else
  580.             fprintf(fp, "%.*s%s", p-l, l, m->m_eol);
  581.         l = p;
  582.         if (*l == '\n')
  583.             l++;
  584.     } while (*l != '\0');
  585. }
  586. /*
  587. **  XUNLINK -- unlink a file, doing logging as appropriate.
  588. **
  589. **    Parameters:
  590. **        f -- name of file to unlink.
  591. **
  592. **    Returns:
  593. **        none.
  594. **
  595. **    Side Effects:
  596. **        f is unlinked.
  597. */
  598.  
  599. void
  600. xunlink(f)
  601.     char *f;
  602. {
  603.     register int i;
  604.  
  605. #ifdef LOG
  606.     if (LogLevel > 20)
  607.         syslog(LOG_DEBUG, "%s: unlink %s", CurEnv->e_id, f);
  608. #endif /* LOG */
  609.  
  610.     i = unlink(f);
  611. #ifdef LOG
  612.     if (i < 0 && LogLevel > 21)
  613.         syslog(LOG_DEBUG, "%s: unlink-fail %d", f, errno);
  614. #endif /* LOG */
  615. }
  616. /*
  617. **  SFGETS -- "safe" fgets -- times out and ignores random interrupts.
  618. **
  619. **    Parameters:
  620. **        buf -- place to put the input line.
  621. **        siz -- size of buf.
  622. **        fp -- file to read from.
  623. **
  624. **    Returns:
  625. **        NULL on error (including timeout).  This will also leave
  626. **            buf containing a null string.
  627. **        buf otherwise.
  628. **
  629. **    Side Effects:
  630. **        none.
  631. */
  632.  
  633. static jmp_buf    CtxReadTimeout;
  634.  
  635. char *
  636. sfgets(buf, siz, fp)
  637.     char *buf;
  638.     int siz;
  639.     FILE *fp;
  640. {
  641.     register EVENT *ev = NULL;
  642.     register char *p;
  643.  
  644.     /* check for reasonable siz arg */
  645.     if (siz < 1)
  646.     {
  647.         buf[0] = '\0';
  648.         return (NULL);
  649.     }
  650.  
  651.     /* set the timeout */
  652.     if (ReadTimeout != 0)
  653.     {
  654.         if (setjmp(CtxReadTimeout) != 0)
  655.         {
  656. #ifdef LOG
  657.             char    *host;
  658.  
  659.             if (RealHostName != NULL)
  660.                 host = RealHostName;
  661.             else if ((host = macvalue('s', CurEnv)) == NULL)
  662.                 host = "local";
  663.             syslog(LOG_NOTICE,
  664.                 "timeout waiting for input from %s", host);
  665. #endif  /* LOG */
  666.             errno = 0;
  667.             usrerr("451 timeout waiting for input");
  668.             buf[0] = '\0';
  669.             return (NULL);
  670.         }
  671.         ev = setevent((TIME_TYPE) ReadTimeout, readtimeout, 0);
  672.     }
  673.  
  674.     /* try to read */
  675.     p = NULL;
  676.     while (p == NULL && !feof(fp) && !ferror(fp))
  677.     {
  678.         errno = 0;
  679.         p = fgets(buf, siz, fp);
  680.         if (errno == EINTR)
  681.             clearerr(fp);
  682.     }
  683.  
  684.     /* clear the event if it has not sprung */
  685.     clrevent(ev);
  686.  
  687.     /* clean up the books and exit */
  688.     LineNumber++;
  689.     if (p == NULL)
  690.     {
  691.         buf[0] = '\0';
  692.         return (NULL);
  693.     }
  694. #ifndef BIT8
  695.     for (p = buf; *p != '\0'; p++)
  696.         *p &= ~0200;
  697. #endif /* !BIT8 */
  698.     return (buf);
  699. }
  700.  
  701. static void
  702. readtimeout()
  703. {
  704.     longjmp(CtxReadTimeout, 1);
  705. }
  706. /*
  707. **  FGETFOLDED -- like fgets, but know about folded lines.
  708. **
  709. **    Parameters:
  710. **        buf -- place to put result.
  711. **        n -- bytes available.
  712. **        f -- file to read from.
  713. **
  714. **    Returns:
  715. **        buf on success, NULL on error or EOF.
  716. **
  717. **    Side Effects:
  718. **        buf gets lines from f, with continuation lines (lines
  719. **        with leading white space) appended.  CRLF's are mapped
  720. **        into single newlines.  Any trailing NL is stripped.
  721. */
  722.  
  723. char *
  724. fgetfolded(buf, n, f)
  725.     char *buf;
  726.     register int n;
  727.     FILE *f;
  728. {
  729.     register char *p = buf;
  730.     register int i;
  731.  
  732.     n--;
  733.     while ((i = getc(f)) != EOF)
  734.     {
  735.         if (i == '\r')
  736.         {
  737.             i = getc(f);
  738.             if (i != '\n')
  739.             {
  740.                 if (i != EOF)
  741.                     (void) ungetc(i, f);
  742.                 i = '\r';
  743.             }
  744.         }
  745.         if (--n > 0)
  746.             *p++ = i;
  747.         if (i == '\n')
  748.         {
  749.             LineNumber++;
  750.             i = getc(f);
  751.             if (i != EOF)
  752.                 (void) ungetc(i, f);
  753.             if (i != ' ' && i != '\t')
  754.             {
  755.                 *--p = '\0';
  756.                 return (buf);
  757.             }
  758.         }
  759.     }
  760.     return (NULL);
  761. }
  762. /*
  763. **  CURTIME -- return current time.
  764. **
  765. **    Parameters:
  766. **        none.
  767. **
  768. **    Returns:
  769. **        the current time.
  770. **
  771. **    Side Effects:
  772. **        none.
  773. */
  774.  
  775. TIME_TYPE
  776. curtime()
  777. {
  778.     auto TIME_TYPE t;
  779.  
  780.     (void) time(&t);
  781.     return ((TIME_TYPE)t);
  782. }
  783. /*
  784. **  ATOBOOL -- convert a string representation to boolean.
  785. **
  786. **    Defaults to "TRUE"
  787. **
  788. **    Parameters:
  789. **        s -- string to convert.  Takes "tTyY" as true,
  790. **            others as false.
  791. **
  792. **    Returns:
  793. **        A boolean representation of the string.
  794. **
  795. **    Side Effects:
  796. **        none.
  797. */
  798.  
  799. bool
  800. atobool(s)
  801.     register const char *s;
  802. {
  803.     if (*s == '\0' || index("tTyY", *s) != NULL)
  804.         return (TRUE);
  805.     return (FALSE);
  806. }
  807. /*
  808. **  ATOOCT -- convert a string representation to octal.
  809. **
  810. **    Parameters:
  811. **        s -- string to convert.
  812. **
  813. **    Returns:
  814. **        An integer representing the string interpreted as an
  815. **        octal number.
  816. **
  817. **    Side Effects:
  818. **        none.
  819. */
  820.  
  821. int
  822. atooct(s)
  823.     register const char *s;
  824. {
  825.     register int i = 0;
  826.  
  827.     while (*s >= '0' && *s <= '7')
  828.         i = (i << 3) | (*s++ - '0');
  829.     return (i);
  830. }
  831. /*
  832. **  WAITFOR -- wait for a particular process id.
  833. **
  834. **    Parameters:
  835. **        pid -- process id to wait for.
  836. **
  837. **    Returns:
  838. **        status of pid.
  839. **        -1 if pid never shows up.
  840. **
  841. **    Side Effects:
  842. **        none.
  843. */
  844.  
  845. int
  846. waitfor(pid)
  847.     int pid;
  848. {
  849.     auto int st;
  850.     int i;
  851.  
  852.     do
  853.     {
  854.         errno = 0;
  855.         i = wait(&st);
  856.         if (i > 0 && tTd(4, 2))
  857.             printf("waitfor: wait (pid = %d)\n", i);
  858.     } while ((i >= 0 || errno == EINTR) && i != pid);
  859.     if (i < 0)
  860.         st = -1;
  861.     return (st);
  862. }
  863. /*
  864. **  BITINTERSECT -- tell if two bitmaps intersect
  865. **
  866. **    Parameters:
  867. **        a, b -- the bitmaps in question
  868. **
  869. **    Returns:
  870. **        TRUE if they have a non-null intersection
  871. **        FALSE otherwise
  872. **
  873. **    Side Effects:
  874. **        none.
  875. */
  876.  
  877. bool
  878. bitintersect(a, b)
  879.     BITMAP a;
  880.     BITMAP b;
  881. {
  882.     int i;
  883.  
  884.     for (i = BITMAPBYTES / sizeof (int); --i >= 0; )
  885.         if ((a[i] & b[i]) != 0)
  886.             return (TRUE);
  887.     return (FALSE);
  888. }
  889. /*
  890. **  BITZEROP -- tell if a bitmap is all zero
  891. **
  892. **    Parameters:
  893. **        map -- the bit map to check
  894. **
  895. **    Returns:
  896. **        TRUE if map is all zero.
  897. **        FALSE if there are any bits set in map.
  898. **
  899. **    Side Effects:
  900. **        none.
  901. */
  902.  
  903. bool
  904. bitzerop(map)
  905.     BITMAP map;
  906. {
  907.     int i;
  908.  
  909.     for (i = BITMAPBYTES / sizeof (int); --i >= 0; )
  910.         if (map[i] != 0)
  911.             return (FALSE);
  912.     return (TRUE);
  913. }
  914.  
  915. /*
  916. **    PRINTCAV -- Print concatenated argument vector
  917. **
  918. **    Parameters:
  919. **        av -- argument vector.
  920. **
  921. **    Returns:
  922. **        none.
  923. **
  924. **    Side Effects:
  925. **        prints av.
  926. */
  927.  
  928. void
  929. printcav(av)
  930.     register char **av;
  931. {
  932.     bool oldCatPrint = catPrint;
  933.  
  934.     catPrint = TRUE;
  935.     printav(av);
  936.     catPrint = oldCatPrint;
  937. }
  938.  
  939. /*
  940. **    WRITEPID -- Write process id to file
  941. **
  942. **    Parameters:
  943. **        none
  944. **
  945. **    Returns:
  946. **        none.
  947. **
  948. **    Side Effects:
  949. **        writes pid file, creating if necessary
  950. */
  951.  
  952. #ifdef _PATH_SENDMAILPID
  953. void
  954. WritePid()
  955. {
  956.     extern char *PidFile;
  957.     FILE *f;
  958.  
  959.     (void) unlink(PidFile);    /* try to be safe :-) */
  960.     if ((f = dfopen(PidFile, "w")) != NULL)
  961.     {
  962.         fprintf(f, "%d\n", getpid());
  963.         (void) chmod(PidFile, 0444);
  964.         (void) fclose(f);
  965.     }
  966. # ifdef LOG
  967.     else
  968.         syslog(LOG_NOTICE, "Could not log daemon pid %d to file %s: %m",
  969.                getpid(), PidFile);
  970. # endif /* LOG */
  971. }
  972. #endif    /* _PATH_SENDMAILPID */
  973.